package com.bcbim.api_web.menu.controller;


import com.bcbim.authentication_interface.menu.dao.MenuDAO;
import com.bcbim.authentication_interface.menu.dto.MenuDTO;
import com.bcbim.authentication_interface.menu.dto.ReductionMenuDTO;
import com.bcbim.authentication_interface.menu.dto.RoleAbilityDTO;
import com.bcbim.authentication_interface.menu.service.MenuService;
import com.bcbim.authentication_interface.menu.vo.MenuDetailVO;
import com.bcbim.authentication_interface.menu.vo.ReductionMenuVO;
import com.bcbim.authentication_interface.menu.vo.RoleMenuAbilityVO;
import com.bcbim.authentication_interface.menu.vo.TreeMenuVO;
import com.bcbim.authentication_interface.util.AuthUtil;
import com.bcbim.common.response.vo.ReturnMsg;
import com.bcbim.common.sys.Code;
import com.bcbim.common.sys.Constant;
import com.bcbim.common.sys.ParamException;
import com.bcbim.common.util.GuidUtil;
import com.bcbim.common.util.ParamCheck;
import com.google.common.collect.Lists;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
import org.apache.dubbo.config.annotation.Reference;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import java.time.LocalDateTime;
import java.util.List;
import java.util.stream.Collectors;

/**
 * @Description: 菜单管理
 * @Author: ye
 * @Date: 2020/11/30
 * @Version: V1.0
 **/
@RestController
@RequestMapping("/menu")
public class MenuManagementController {

    @Reference(protocol = "dubbo", group = "menu", version = "1.0.0")
    private MenuService menuServiceImpl;

    /**
     * @return ReturnMsg
     * @Description 新增菜单
     * @Author XueHao
     * @Date 2021/8/18
     */
    @PostMapping("/insertMenu")
    public ReturnMsg insertMenu(MenuDAO menuDAO) {
        // 参数校验
        try {
            ParamCheck.stringNotEmpty(menuDAO.getApplicationPlatform(), Constant.CODE_LENGTH_ONE);
            ParamCheck.idCanBeEmpty(menuDAO.getParentId());
            ParamCheck.stringNotEmpty(menuDAO.getMenuName(), 20);
            ParamCheck.stringCanBeEmpty(menuDAO.getIcon(), 20);
            ParamCheck.stringNotEmpty(menuDAO.getUrl(), 100);
            ParamCheck.stringNotEmpty(menuDAO.getEnable(), Constant.CODE_LENGTH_ONE);
            ParamCheck.objectNotEmpty(menuDAO.getQueueNumber());
            ParamCheck.stringCanBeEmpty(menuDAO.getRemark(),500);
        } catch (ParamException e) {
            return ReturnMsg.consFail(ParamException.PARAMETER_ERROR);
        }
        // 整理参数 : id, 创建人, 创建时间, 删除标记
        menuDAO.setId(GuidUtil.get());
        menuDAO.setCreateBy(AuthUtil.getUserIdDecrypt());
        menuDAO.setCreateTime(LocalDateTime.now());
        menuDAO.setDel(Constant.NOT_DEL);
        // 写入数据库
        int result = menuServiceImpl.insertMenu(menuDAO);
        return result == 1 ? ReturnMsg.consSuccess(Constant.SAVE_SUCCESS) : ReturnMsg.consFail(Constant.SAVE_FAIL);
    }

    /**
     * @return ReturnMsg
     * @Description 菜单下拉列表
     * @Author XueHao
     * @Date 2021/8/18
     */
    @PostMapping("/selectMenu")
    public ReturnMsg selectMenu(MenuDTO menuDTO) {
        // 参数校验
        try {
            ParamCheck.stringNotEmpty(menuDTO.getApplicationPlatform(), Constant.CODE_LENGTH_ONE);
        } catch (ParamException e) {
            return ReturnMsg.consFail(ParamException.PARAMETER_ERROR);
        }
        // 查询数据库
        List<Code> list = menuServiceImpl.selectMenu(menuDTO);
        return ReturnMsg.consSuccess(list);
    }

    /**
     * @return ReturnMsg
     * @Description 更新菜单信息
     * @Author XueHao
     * @Date 2021/8/18
     */
    @PostMapping("/updateMenu")
    public ReturnMsg updateMenu(MenuDAO menuDAO) {
        // 参数校验
        try {
            ParamCheck.idCheck(menuDAO.getId());
            ParamCheck.stringNotEmpty(menuDAO.getApplicationPlatform(), Constant.CODE_LENGTH_ONE);
            ParamCheck.idCanBeEmpty(menuDAO.getParentId());
            ParamCheck.stringNotEmpty(menuDAO.getMenuName(), 20);
            ParamCheck.stringCanBeEmpty(menuDAO.getIcon(), 20);
            ParamCheck.stringNotEmpty(menuDAO.getUrl(), 100);
            ParamCheck.stringNotEmpty(menuDAO.getEnable(), Constant.CODE_LENGTH_ONE);
            ParamCheck.objectNotEmpty(menuDAO.getQueueNumber());
        } catch (ParamException e) {
            return ReturnMsg.consFail(ParamException.PARAMETER_ERROR);
        }
        // 整理参数 : 修改人, 修改时间
        menuDAO.setUpdateBy(AuthUtil.getUserIdDecrypt());
        menuDAO.setUpdateTime(LocalDateTime.now());
        //写入数据库
        int res = menuServiceImpl.updateMenu(menuDAO);
        return res == 1 ? ReturnMsg.consSuccess(Constant.SAVE_SUCCESS) : ReturnMsg.consFail(Constant.SAVE_FAIL);
    }

    /**
     * @return ReturnMsg
     * @Description 删除菜单信息
     * @Author XueHao
     * @Date 2021/8/18
     */
    @PostMapping("/removeMenu")
    public ReturnMsg removeMenu(String id) {
        // 参数校验
        try {
            ParamCheck.idCheck(id);
        } catch (ParamException e) {
            return ReturnMsg.consFail(ParamException.PARAMETER_ERROR);
        }
        boolean b = menuServiceImpl.getMenuCountByParentId(id);
        if (b) {
            // 整理参数: id、修改人、修改时间、删除标记
            MenuDAO menuDAO = new MenuDAO();
            menuDAO.setId(id);
            menuDAO.setUpdateBy(AuthUtil.getUserIdDecrypt());
            menuDAO.setUpdateTime(LocalDateTime.now());
            menuDAO.setDel(Constant.DEL);
            // 写入数据库
            int result = menuServiceImpl.removeMenu(menuDAO);
            return result == 1 ? ReturnMsg.consSuccess(Constant.DEL_SUCCESS) : ReturnMsg.consFail(Constant.DEL_FAIL);
        } else {
            return ReturnMsg.consFail("该菜单下存在子菜单，请先移除子菜单再删除父级菜单！");
        }
    }

    /**
     * @return ReturnMsg
     * @Description 查询菜单信息列表
     * @Author XueHao
     * @Date 2021/8/18
     */
    @PostMapping("/listMenu")
    public ReturnMsg listMenu(MenuDTO menuDTO) {
        // 参数校验
        try {
            ParamCheck.stringNotEmpty(menuDTO.getApplicationPlatform(), Constant.CODE_LENGTH_ONE);
        } catch (ParamException e) {
            return ReturnMsg.consFail(ParamException.PARAMETER_ERROR);
        }
        // 整理参数: 删除标记
        menuDTO.setDel(Constant.NOT_DEL);
        // 查询菜单信息数据集合
        List<TreeMenuVO> listMenuVO = menuServiceImpl.listMenu(menuDTO);
        // 若菜单数据列表为空, 则返回空对象
        if (CollectionUtils.isEmpty(listMenuVO)) {
            return ReturnMsg.consSuccess();
        }
        // 组装菜单树, 跟节点 parentId == null 或 parentId == ""
        List<TreeMenuVO> listMenu = assembleMenuTree(listMenuVO, null, menuDTO.getMenuName());
        return ReturnMsg.consSuccess(listMenu);
    }

    /**
     * @Description: 递归组装菜单属性列表
     * @Param: listMenu 菜单数据列表
     * @Param: id 当前菜单id
     * @Param: menuName 搜索条件--菜单名称
     * @Return: List<TreeMenuVO>
     * @Author: haoshuai
     * @Date: 2021/7/5
     */
    private List<TreeMenuVO> assembleMenuTree(List<TreeMenuVO> listMenu, String id, String menuName) {
        // 创建菜单树存储对象
        List<TreeMenuVO> treeList = Lists.newArrayList();
        // 遍历 递归整理子菜单
        listMenu.forEach(menu -> {
            // 由于菜单修改后, parentId 字段可能为空字符串, 估整理为统一的 null
            String parentId = StringUtils.isEmpty(menu.getParentId()) ? null : menu.getParentId();
            if (StringUtils.equals(id, parentId)) {
                menu.setChildren(assembleMenuTree(listMenu, menu.getId(), menuName));
                treeList.add(menu);
            }
        });
        return treeList;
    }

    /**
     * 查询菜单详情
     *
     * @param id id
     * @return ReturnMsg
     * @author XueHao
     * @date 2021/12/1
     */
    @PostMapping("/getMenuDetail")
    public ReturnMsg getMenuDetail(String id) {
        //参数校验
        try {
            ParamCheck.idCheck(id);
        } catch (ParamException e) {
            return ReturnMsg.consFail(ParamException.PARAMETER_ERROR);
        }
        //查询菜单详情
        MenuDetailVO menuDetailVO = menuServiceImpl.getMenuDetail(id);
        String parentName = menuServiceImpl.getParentName(menuDetailVO.getParentId());
        menuDetailVO.setParentName(parentName);
        return ReturnMsg.consSuccess(menuDetailVO);
    }

    /**
     * @Description: 获取菜单按钮权限功能
     * @Return: ReturnMsg
     * @Author: haoshuai
     * @Date: 2021/7/7
     */
    @PostMapping("/listMenuAbility")
    public ReturnMsg listMenuAbility(String applicationPlatform) {
        try {
            ParamCheck.stringNotEmptyRegexpCheck(applicationPlatform , "^[1|2|3|4]$");
        } catch (ParamException e) {
            return ReturnMsg.consFail(ParamException.PARAMETER_ERROR);
        }
        // 获取登录用户id
        String userId = AuthUtil.getUserIdDecrypt();

        // 查询登录用户拥有的菜单
        List<RoleMenuAbilityVO> listRoleMenuVO = menuServiceImpl.listRoleMenu(userId, applicationPlatform);

        // 查询登录用户拥有的功能
        List<RoleAbilityDTO> listRoleAbilityDto = menuServiceImpl.listRoleAbility(userId, applicationPlatform);

        // 组装权限菜单功能对象
        List<RoleMenuAbilityVO> listRoleMenu = assembleRoleMenuAbility(listRoleMenuVO, null, listRoleAbilityDto);

        return ReturnMsg.consSuccess(listRoleMenu);
    }

    /**
     * @Description: 递归组装权限菜单功能对象
     * @Param: listRoleMenu 权限菜单列表
     * @Param: id 当前菜单id
     * @Param: listRoleAbility 权限功能列表
     * @Return: List<RoleAbilityDto>
     * @Author: haoshuai
     * @Date: 2021/7/7
     */
    private List<RoleMenuAbilityVO> assembleRoleMenuAbility(List<RoleMenuAbilityVO> listRoleMenu, String id, List<RoleAbilityDTO> listRoleAbility) {

        // 创建权限菜单功能存储对象
        List<RoleMenuAbilityVO> resList = Lists.newArrayList();

        // 遍历 递归整理菜单
        listRoleMenu.forEach(roleMenu -> {
            // 由于菜单修改后, parentId 字段可能为空字符串, 估整理为统一的 null
            String parentId = StringUtils.isEmpty(roleMenu.getParentId()) ? null : roleMenu.getParentId();
            if (StringUtils.equals(id, parentId)) {
                // 递归整理自菜单信息
                roleMenu.setChildren(assembleRoleMenuAbility(listRoleMenu, roleMenu.getId(), listRoleAbility));
                // 整理该菜单功能, 写入roleMenu对象
                List<RoleAbilityDTO> list = assembleRoleAbility(roleMenu.getId(), listRoleAbility);
                roleMenu.setRoleAbility(list);
                resList.add(roleMenu);
            }
        });

        return resList;
    }

    /**
     * @Description: 整理该菜单功能
     * @Param: id 菜单id
     * @Param: listRoleAbility 权限功能列表
     * @Return: List<RoleAbilityDto>
     * @Author: haoshuai
     * @Date: 2021/7/7
     */
    private List<RoleAbilityDTO> assembleRoleAbility(String id, List<RoleAbilityDTO> listRoleAbility) {
        // 取菜单id 和 权限功能列表中 menuId 相等的数据
        return listRoleAbility.stream().filter(roleAbility -> StringUtils.equals(id, roleAbility.getMenuId()))
                .collect(Collectors.toList());
    }

    /**
     * @Description: 还原角色菜单权限(v2)
     * @Param: ReductionMenuDTO
     * @Return: ReturnMsg
     * @Author: ye
     * @Date: 2021/9/13
     */
    @PostMapping("reductionMenu")
    public ReturnMsg reductionMenu(ReductionMenuDTO query) {
        try {
            ParamCheck.idCheck(query.getMenuId());
            ParamCheck.idCheck(query.getRoleId());
        } catch (ParamException e) {
            return ReturnMsg.consFail(ParamException.PARAMETER_ERROR);
        }
        // 还原角色功能（搜索没有修改之前的勾选的菜单id和功能按钮id）
        List<String> roleMenuList = menuServiceImpl.reductionMenu(query);
        List<String> roleMenuAbilityList = menuServiceImpl.reductionMenuAbility(query);
        ReductionMenuVO result = new ReductionMenuVO();
        result.setMenuId(roleMenuList);
        result.setAbilityId(roleMenuAbilityList);
        return ReturnMsg.consSuccess(result);
    }
}
